﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Vortex.SceneFramework.CSS {
	
	/// <summary>
	/// Element styles overrides. Setting element style property hides style property provided by style sheet. 
	/// It is similar to web DOM model.
	/// </summary>
	public class NodeStyle {
		///<summary>Owner element of this style instance</summary>
		private IStyledNode _owner;
		///<summary>Style value set of element overrides</summary>
		private StyleValueSet _values = new StyleValueSet();
		///<summary>Computed element style values set</summary>
		private StyleValueSet _computedValues = new StyleValueSet();
		///<summary>Flag that marks style as entirely discarded</summary>
		private bool _isDiscarded = true;

		/// <summary>
		/// Initializes a new instance of the <see cref="ElementStyle"/> class.
		/// </summary>
		public NodeStyle(IStyledNode owner) {
			_owner = owner;
		}

		#region Public Interface

		/// <summary>
		/// Sets the style value override for the specified property. Gets the computed element style property value.
		/// </summary>
		/// <value>Style value object. Is <c>null</c> if there are no override.</value>
		public object this[StyleKey key] {
			get {
				CheckRecompute();
				return _computedValues[key].Value;
			}
			set {
				//discards computed style
				Discard();
				//if assigned value is null then default value will be set
				if (value != null) {
					_values[key] = new StyleValue(value, StyleValue.MAX_IMPORTANCE);
				} else {
					_values[key] = new StyleValue(StyleSheet.GetPropertyInfo(key.Index).DefaultValue, StyleValue.DEFAULT_IMPORTANCE);				
				}				
			}
		}

		/// <summary>
		/// Gets the computed value of specified property.
		/// </summary>
		/// <typeparam name="T">Type of style property value</typeparam>
		/// <param name="property">The style property key.</param>
		/// <returns>Value of computed style property</returns>
		public T Get<T>(StyleKey key) {
			CheckRecompute();
			return (T)_computedValues[key].Value;
		}

		/// <summary>
		/// Clears all of style value overrides.
		/// </summary>
		public void Clear() {
			_values.Clear();
			Discard();
		}

		/// <summary>
		/// Discards the element style.
		/// </summary>
		public void Discard() {
			_isDiscarded = true;
		}

		#endregion

		/// <summary>
		/// Checks the style to be recomputed if it is discarded.
		/// </summary>
		private void CheckRecompute() {
			if (_isDiscarded) {
				Recompute();
			}
		}

		/// <summary>
		/// Recomputes this style values.
		/// </summary>
		private void Recompute() {
			//first, copy all of values from element overrides
			_computedValues.Copy(_values);

			//check is there stylesheet is available
			StyleSheet styleSheet = _owner.StyleSheet;			
			if (null != styleSheet) {
				foreach (StyleValueSet valueSet in styleSheet.GetElementStyles(_owner)) {
					_computedValues.Merge(valueSet);
				}
			}

			//unmark entity as discarded
			_isDiscarded = false;
		}

	}
}
